﻿using System;
using System.Data.Common;

namespace Sofire.Data
{
    /// <summary>
    /// 表示数据库查询操作的返回结果。
    /// </summary>
    /// <typeparam name="TValue">返回值的类型。</typeparam>
    public abstract class QueryResultBase<TValue> : Result<TValue>, IQueryResult<TValue>
    {
        #region Fields

        /// <summary>
        /// 表示查询操作的 <see cref="System.Data.Common.DbCommand"/> 对象。
        /// </summary>
        protected DbCommand _Command;

        /// <summary>
        /// 设置或获取一个值，指示是否启用析构方法。默认为 true，表示自动释放所有使用的资源。
        /// </summary>
        protected bool _destructor = true;

        /// <summary>
        /// 表示数据库的操作引擎。
        /// </summary>
        protected QueryEngineBase _QueryEngine;

        private bool _IsDisposed;

        #endregion Fields

        #region Constructors

        /// <summary>
        /// 初始化 <see cref="Sofire.Data.QueryResultBase&lt;TValue&gt;"/> 的新实例。
        /// </summary>
        internal QueryResultBase()
        {
        }

        /// <summary>
        /// 析构方法。
        /// </summary>
        ~QueryResultBase()
        {
            if(this._destructor)
                this.Dispose();
        }

        #endregion Constructors

        #region Properties

        /// <summary>
        /// 获取一个值，表示查询操作的 <see cref="System.Data.Common.DbCommand"/> 对象。
        /// </summary>
        public DbCommand Command
        {
            get { return this._Command; }
        }

        /// <summary>
        /// 获取一个值，表示当前查询结果是否已释放资源。
        /// </summary>
        public bool IsDisposed
        {
            get { return this._IsDisposed; }
        }

        /// <summary>
        /// 获取一个值，表示数据库的操作引擎。
        /// </summary>
        public QueryEngineBase QueryEngine
        {
            get { return this._QueryEngine; }
        }

        object IQueryResult.Value
        {
            get
            {
                return this._Value;
            }
        }

        #endregion Properties

        #region Indexers

        /// <summary>
        /// 指定参数的名称，获取一个参数的值。
        /// </summary>
        /// <param name="parameterName">参数的名称。</param>
        /// <returns>返回具有指定名称的参数值。</returns>
        public object this[string parameterName]
        {
            get { return this._Command.Parameters[parameterName].Value; }
        }

        /// <summary>
        /// 指定参数的索引，获取一个参数的值。
        /// </summary>
        /// <param name="parameterIndex">参数的从零开始的索引。</param>
        /// <returns>返回索引处的参数值。</returns>
        public object this[int parameterIndex]
        {
            get { return this._Command.Parameters[parameterIndex].Value; }
        }

        #endregion Indexers

        #region Methods

        /// <summary>
        /// 释放由 <see cref="Sofire.Data.QueryResultBase&lt;TValue&gt;"/> 使用的所有资源。
        /// </summary>
        public void Dispose()
        {
            if(!this._IsDisposed)
            {
                this.Disposing();

                if(!ValueType.IsValueType && ValueType.IsAssignableFrom(typeof(IDisposable)))
                {
                    (this._Value as IDisposable).TryDispose();
                }

                this.ToSuccessed();
                if(this._Command != null)
                {
                    this._Command.Parameters.Clear();
                    this._Command.Dispose();
                    this._Command = null;
                }
                this._Value = default(TValue);
                this._IsDisposed = true;

                //GC.SuppressFinalize(this);
            }
        }

        /// <summary>
        /// 初始化查询操作的返回结果。
        /// </summary>
        /// <param name="queryEngine">数据库的操作引擎。</param>
        /// <param name="command">查询操作的 <see cref="System.Data.Common.DbCommand"/> 对象。</param>
        /// <param name="value">查询操作的返回值。</param>
        /// <param name="exception">查询操作的引发的异常。</param>
        internal virtual void Initialization(QueryEngineBase queryEngine, DbCommand command, TValue value, Exception exception)
        {
            this._QueryEngine = queryEngine;
            this._Command = command;
            if(exception == null)
                this._Value = value;
            this.ToFailded(exception);
        }

        /// <summary>
        /// 执行释放任务。
        /// </summary>
        protected virtual void Disposing()
        {
            #if DEBUG
            System.Diagnostics.Debug.WriteLine(this.GetType());
            #endif
        }

        #endregion Methods
    }
}